ioctl: add UncheckedV4l2Buffer structure Add a structure that fully owns a non-checked V4L2 buffer. This will enable a better replacement for the QueryBuf trait while being usable in more places, and become the standard for ioctls that work on struct v4l2_buffer. 
diff --git a/lib/src/ioctl.rs b/lib/src/ioctl.rs index 2fab9e2..1141e3b 100644 --- a/lib/src/ioctl.rs +++ b/lib/src/ioctl.rs 
@@ -93,6 +93,8 @@  pub use streamon::*;  pub use subscribe_event::*;   +use std::convert::Infallible; +use std::convert::TryFrom;  use std::ffi::CStr;  use std::ffi::FromBytesWithNulError;  use std::fmt::Debug; @@ -102,6 +104,7 @@  use bitflags::bitflags;  use enumn::N;  use nix::errno::Errno; +use thiserror::Error;    use crate::bindings;  use crate::memory::DmaBuf; @@ -142,6 +145,21 @@  }  }   +/// A fully owned V4L2 buffer obtained from some untrusted place, probably an ioctl. +/// +/// Its only valid purpose it to be moved around and converted into something safer like +/// [`V4l2Buffer`]. +pub struct UncheckedV4l2Buffer(pub bindings::v4l2_buffer, pub Option<V4l2BufferPlanes>); + +/// For cases where we are not interested in the result of `qbuf` +impl TryFrom<UncheckedV4l2Buffer> for () { + type Error = Infallible; + + fn try_from(_: UncheckedV4l2Buffer) -> Result<Self, Self::Error> { + Ok(()) + } +} +  /// A memory area we can pass to ioctls in order to get/set plane information  /// with the multi-planar API.  type V4l2BufferPlanes = [bindings::v4l2_plane; bindings::VIDEO_MAX_PLANES as usize]; @@ -778,6 +796,34 @@  Overlay,  }   +#[derive(Debug, Error)] +pub enum V4l2BufferFromError { + #[error("unknown queue type {0}")] + UnknownQueueType(u32), + #[error("unknown memory type {0}")] + UnknownMemoryType(u32), +} + +impl TryFrom<UncheckedV4l2Buffer> for V4l2Buffer { + type Error = V4l2BufferFromError; + + /// Do some consistency checks to ensure methods of `V4l2Buffer` that do an `unwrap` can never + /// fail. + fn try_from(buffer: UncheckedV4l2Buffer) -> Result<Self, Self::Error> { + let v4l2_buf = buffer.0; + let v4l2_planes = buffer.1; + QueueType::n(v4l2_buf.type_) + .ok_or(V4l2BufferFromError::UnknownQueueType(v4l2_buf.type_))?; + MemoryType::n(v4l2_buf.memory) + .ok_or(V4l2BufferFromError::UnknownMemoryType(v4l2_buf.memory))?; + + Ok(Self { + buffer: v4l2_buf, + planes: v4l2_planes.unwrap_or_default(), + }) + } +} +  #[cfg(test)]  mod tests {  #[test]